package modbus

var (

	// Success 成功,无此控制码,用于函数返回成功标识
	Success Control = 0x00

	// ReadCoils 读线圈
	// 在一个远程设备中，使用该功能码读取线圈的 1 至 2000 连续状态。请求 PDU 详细说明了起始
	// 地址，即指定的第一个线圈地址和线圈编号。从零开始寻址线圈。因此寻址线圈 1-16 为 0-15。
	// 根据数据域的每个比特将响应报文中的线圈分成为一个线圈。指示状态为 1= ON 和 0= OFF。
	// 第一个数据字节的 LSB（最低有效位）包括在询问中寻址的输出。其它线圈依次类推，一直到这个
	// 字节的高位端为止，并在后续字节中从低位到高位的顺序。
	// 如果返回的输出数量不是八的倍数，将用零填充最后数据字节中的剩余比特（一直到字节的高
	// 位端）。字节数量域说明了数据的完整字节数。
	ReadCoils Control = 0x01

	// ReadDiscreteInputs 读离散量输入
	// 在一个远程设备中，使用该功能码读取离散量输入的 1 至 2000 连续状态。请求 PDU 详细说明
	// 了起始地址，即指定的第一个输入地址和输入编号。从零开始寻址输入。因此寻址输入 1-16 为 0-15。
	// 根据数据域的每个比特将响应报文中的离散量输入分成为一个输入。指示状态为 1= ON 和 0=
	// OFF。第一个数据字节的 LSB（最低有效位）包括在询问中寻址的输入。其它输入依次类推，一直
	// 到这个字节的高位端为止，并在后续字节中从低位到高位的顺序。
	// 如果返回的输入数量不是八的倍数，将用零填充最后数据字节中的剩余比特（一直到字节的高
	// 位端）。字节数量域说明了数据的完整字节数
	ReadDiscreteInputs Control = 0x02

	// ReadHoldingRegisters 读保持寄存器
	// 在一个远程设备中，使用该功能码读取保持寄存器连续块的内容。请求 PDU 说明了起始寄存器
	// 地址和寄存器数量。从零开始寻址寄存器。因此，寻址寄存器 1-16 为 0-15。
	// 将响应报文中的寄存器数据分成每个寄存器有两字节，在每个字节中直接地调整二进制内容。
	// 对于每个寄存器，第一个字节包括高位比特，并且第二个字节包括低位比特。
	ReadHoldingRegisters Control = 0x03

	// ReadInputRegisters 读输入寄存
	// 在一个远程设备中，使用该功能码读取 1 至大约 125 的连续输入寄存器。请求 PDU 说明了起始
	// 地址和寄存器数量。从零开始寻址寄存器。因此，寻址输入寄存器 1-16 为 0-15。
	// 将响应报文中的寄存器数据分成每个寄存器为两字节，在每个字节中直接地调整二进制内容。
	// 对于每个寄存器，第一个字节包括高位比特，并且第二个字节包括低位比特。
	ReadInputRegisters Control = 0x04

	// WriteCoils 写单个线圈
	// 在一个远程设备上，使用该功能码写单个输出为 ON 或 OFF。
	// 请求数据域中的常量说明请求的 ON/OFF 状态。十六进制值 FF 00 请求输出为 ON。十六进制值
	// 00 00 请求输出为 OFF。其它所有值均是非法的，并且对输出不起作用。
	// 请求 PDU 说明了强制的线圈地址。从零开始寻址线圈。因此，寻址线圈 1 为 0。线圈值域的常
	// 量说明请求的 ON/OFF 状态。十六进制值 0XFF00 请求线圈为 ON。十六进制值 0X0000 请求线圈为
	// OFF。其它所有值均为非法的，并且对线圈不起作用。
	// 正常响应是请求的应答，在写入线圈状态之后返回这个正常响应。
	WriteCoils Control = 0x05

	// WriteRegisters 写单个寄存器
	// 在一个远程设备中，使用该功能码写单个保持寄存器。
	// 请求 PDU 说明了被写入寄存器的地址。从零开始寻址寄存器。因此，寻址寄存器 1 为 0。
	// 正常响应是请求的应答，在写入寄存器内容之后返回这个正常响应。
	WriteRegisters Control = 0x06

	// WriteMultipleCoils 写多个线圈
	// 在一个远程设备中，使用该功能码强制线圈序列中的每个线圈为 ON 或 OFF。请求 PDU 说明了
	// 强制的线圈参考。从零开始寻址线圈。因此，寻址线圈 1 为 0。
	// 请求数据域的内容说明了被请求的 ON/OFF 状态。域比特位置中的逻辑“1”请求相应输出为
	// ON。域比特位置中的逻辑“0”请求相应输出为 OFF。
	// 正常响应返回功能码、起始地址和强制的线圈数量。
	WriteMultipleCoils Control = 0x0F

	// WriteMultipleRegisters 写多个寄存器
	// 在一个远程设备中，使用该功能码写连续寄存器块(1 至约 120 个寄存器)。
	// 在请求数据域中说明了请求写入的值。每个寄存器将数据分成两字节。
	// 正常响应返回功能码、起始地址和被写入寄存器的数量。
	WriteMultipleRegisters Control = 0x10

	// ReadFileLog 读文件记录
	//使用该功能码进行文件记录读取。根据字节数量提供所有请求数据长度，并且根据寄存器提供
	// 所有记录长度。
	// 文件是记录的结构。每个文件包括 10000 个记录，寻址这些记录为十进制 0000 至 9999 或十六
	// 进制 0X0000 至 0X270F，例如寻址记录 12 为 12。
	// 该功能可以读取多个参考组。这些组可以是分散的(不连续的)，但每组中的参考必须是连续的。
	// 用含有 7 个字节的独立“子请求”域定义每个组：
	// 参考类型：1 个字节(必须规定为 6)
	// 文件号：2 个字节
	// GB/T ××××—××××
	// 27
	// 文件中的起始记录号：2 个字节
	// 被读出的记录长度：2 个字节
	// 被读取的寄存器数量不能超过 MODBUS 报文允许的长度：256 个字节，这个寄存器数量与预期
	// 响应中的所有其它域组合。
	// 正常响应是一系列“子响应”，与“子请求”一一对应。字节数域是所有“子响应”中的全部组
	// 合字节数。另外，每个“子响应”都包括一个表示自身字节数的域。
	ReadFileLog Control = 0x14

	// WriteFileLog 写文件记录
	// 使用该功能码进行文件记录写入。根据字节数量提供所有请求数据长度，并且根据 16 比特字的
	// GB/T ××××—××××
	// 29
	// 数量提供所有记录长度。
	// 文件是记录的结构。每个文件包括 10000 个记录，寻址这些记录为十进制 0000 至 9999 或十六
	// 进制 0X0000 至 0X270F，例如寻址记录 12 为 12。
	// 该功能可以写多个参考组。这些组可以是分散的，即不连续的，但每组内的参考必须是连续的。
	// 用含有 7 个字节和数据的独立“子请求”域定义每个组：
	// 参考类型：1 个字节(必须规定为 6)
	// 文件号：2 个字节
	// 文件中的起始记录号：2 个字节
	// 被写入的记录长度：2 个字节
	// 被写入的数据：每个寄存器为 2 字节。
	// 被写入的寄存器数量不能超过 MODBUS 报文允许的长度：256 个字节，这个寄存器数量与询问
	// 中的所有其它域组合。
	// 正常响应是请求的应答。
	WriteFileLog Control = 0x15

	// MaskWriteRegisters 屏蔽写寄存器
	// 该功能码用于通过利用 AND 屏蔽、OR 屏蔽以及寄存器内容的组合来修改特定保持寄存器的内
	// 容。使用这个功能设置或清除寄存器中的单个比特。
	// 请求说明了被写入的保持寄存器、AND 屏蔽使用的数据以及 OR 屏蔽使用的数据。
	// 从 0 开始寻址寄存器。因此，寻址寄存器 1-16 为 0-15。
	// 功能的算法为：
	// 结果= (当前内容 AND And_Mask) OR (Or_Mask AND And_Mask)
	// 例如：
	// GB/T ××××—××××
	// 32
	// 十六进制 二进制
	// 当前内容 = 12 0001 0010
	// And_Mask = F2 1111 0010
	// Or_Mask = 25 0010 0101
	// And_Mask = 0D 0000 1101
	// 结果= 17 0001 0111
	// 注：
	// 如果 Or_Mask 值为零，那么结果是当前内容和 And_Mask 的简单逻辑 AND（与）。如果 And_Mask 值为
	// 零，结果等于 Or_Mask 值。
	// 可以使用读保持寄存器功能（功能码 03）读出寄存器的内容。于是，当控制器扫描它的用户逻辑程序时，
	// 随后可以改变寄存器的内容。
	// 正常的响应是请求的应答。在已经写入寄存器之后，返回响应
	MaskWriteRegisters Control = 0x16

	// ReadWriteMultipleRegisters 读/写多个寄存器
	// 在一个单独 MODBUS 事务中，这个功能码实现了一个读操作和一个写操作的组合。
	// 从零开始寻址保持寄存器。因此，寻址保持寄存器 1-16 为 0-15。
	// 请求说明了起始地址、被读取的保持寄存器号和起始地址、保持寄存器号以及被写入的数据。
	// 在写数据域中，字节数说明随后的字节号。
	// 正常响应包括被读出的寄存器组的数据。在读数据域中，字节数域说明随后的字节数量。
	ReadWriteMultipleRegisters Control = 0x17

	//=====================FAIL=====================

	/*


		失败代码 名称 含义

		01 非法功能 对于服务器(或从站)来说，询问中接收到的功能码是不可允许的操作。这也许
		是因为功能码仅仅适用于新设备而在被选单元中是不可实现的。同时，还指出
		服务器(或从站)在错误状态中处理这种请求，例如：因为它是未配置的，并且
		要求返回寄存器值。

		02 非法数据地址 对于服务器(或从站)来说，询问中接收到的数据地址是不可允许的地址。特别
		是，参考号和传输长度的组合是无效的。对于带有 100 个寄存器的控制器来说，
		带有偏移量 96 和长度 4 的请求会成功，带有偏移量 96 和长度 5 的请求将产生
		异常码 02。
		GB/T ××××—××××
		42
		03 非法数据值 对于服务器(或从站)来说，询问中包括的值是不可允许的值。这个值指示了组
		合请求剩余结构中的故障，例如：隐含长度是不正确的。并不意味着，因为
		MODBUS 协议不知道任何特殊寄存器的任何特殊值的重要意义，寄存器中被
		提交存储的数据项有一个应用程序期望之外的值。

		04 从站设备故障 当服务器(或从站)正在设法执行请求的操作时，产生不可重新获得的差错。

		05 确认 与编程命令一起使用。服务器(或从站)已经接受请求，并切正在处理这个请求，
		但是需要长的持续时间进行这些操作。返回这个响应防止在客户机(或主站)中
		发生超时错误。客户机(或主站)可以继续发送轮询程序完成报文来确定是否完
		成处理。

		06 从属设备忙 与编程命令一起使用。服务器(或从站)正在处理长持续时间的程序命令。张服
		务器(或从站)空闲时，用户(或主站)应该稍后重新传输报文。

		08 存储奇偶性差错 与功能码 20 和 21 以及参考类型 6 一起使用，指示扩展文件区不能通过一致性
		校验。
		服务器(或从站)设法读取记录文件，但是在存储器中发现一个奇偶校验错误。
		客户机(或主方)可以重新发送请求，但可以在服务器(或从站)设备上要求服务。

		0A 不可用网关路径 与网关一起使用，指示网关不能为处理请求分配输入端口至输出端口的内部通
		信路径。通常意味着网关是错误配置的或过载的。

		0B 网关目标设备响应失败
		与网关一起使用，指示没有从目标设备中获得响应。通常意味着设备未在网络
		中


	*/

	// IllegalFunction 非法功能
	// 对于服务器(或从站)来说，询问中接收到的功能码是不可允许的操作。这也许
	// 是因为功能码仅仅适用于新设备而在被选单元中是不可实现的。同时，还指出
	// 服务器(或从站)在错误状态中处理这种请求，例如：因为它是未配置的，并且
	// 要求返回寄存器值。
	IllegalFunction Control = 0x81

	// IllegalAddress 非法数据地址
	// 对于服务器(或从站)来说，询问中接收到的数据地址是不可允许的地址。特别
	// 是，参考号和传输长度的组合是无效的。对于带有 100 个寄存器的控制器来说，
	// 带有偏移量 96 和长度 4 的请求会成功，带有偏移量 96 和长度 5 的请求将产生
	// 异常码 02。
	IllegalAddress Control = 0x82

	// IllegalData 非法数据值
	// 对于服务器(或从站)来说，询问中包括的值是不可允许的值。这个值指示了组
	// 合请求剩余结构中的故障，例如：隐含长度是不正确的。并不意味着，因为
	// MODBUS 协议不知道任何特殊寄存器的任何特殊值的重要意义，寄存器中被
	// 提交存储的数据项有一个应用程序期望之外的值
	IllegalData Control = 0x83

	// DeviceFault 从站设备故障
	// 当服务器(或从站)正在设法执行请求的操作时，产生不可重新获得的差错。
	DeviceFault Control = 0x84

	// DeviceConfirm 确认
	// 与编程命令一起使用。服务器(或从站)已经接受请求，并切正在处理这个请求，
	// 但是需要长的持续时间进行这些操作。返回这个响应防止在客户机(或主站)中
	// 发生超时错误。客户机(或主站)可以继续发送轮询程序完成报文来确定是否完
	// 成处理
	DeviceConfirm Control = 0x85

	// DeviceBusy 从属设备忙
	// 与编程命令一起使用。服务器(或从站)正在处理长持续时间的程序命令。张服
	// 务器(或从站)空闲时，用户(或主站)应该稍后重新传输报文。
	DeviceBusy Control = 0x86

	// ParityError 存储奇偶性差错
	// 与功能码 20 和 21 以及参考类型 6 一起使用，指示扩展文件区不能通过一致性
	// 校验。
	// 服务器(或从站)设法读取记录文件，但是在存储器中发现一个奇偶校验错误。
	// 客户机(或主方)可以重新发送请求，但可以在服务器(或从站)设备上要求服务。
	ParityError Control = 0x88

	// UnusableGatewayPath 不可用网关路径
	// 与网关一起使用，指示网关不能为处理请求分配输入端口至输出端口的内部通
	// 信路径。通常意味着网关是错误配置的或过载的。
	UnusableGatewayPath Control = 0x8A

	// GatewayResponseFail 网关目标设备响应失败
	// 与网关一起使用，指示没有从目标设备中获得响应。通常意味着设备未在网络中。
	GatewayResponseFail Control = 0x8B
)

type Control byte

func (this Control) Int() int {
	return int(this)
}

func (this Control) Byte() byte {
	return byte(this)
}

func (this Control) Error() string {
	switch this {
	case IllegalFunction:
		return "非法功能"
	case IllegalAddress:
		return "非法数据地址"
	case IllegalData:
		return "非法数据值"
	case DeviceFault:
		return "从站设备故障"
	case DeviceConfirm:
		return "正在处理"
	case DeviceBusy:
		return "从属设备忙"
	case ParityError:
		return "存储奇偶性差错"
	case UnusableGatewayPath:
		return "不可用网关路径"
	case GatewayResponseFail:
		return "网关目标设备响应失败"
	default:
		return "未知控制码"
	}
}
